// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: jshin

#pragma once

#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <unordered_map>
#include <vector>

#include "coin2/exchange/base/market/market_exchange_api.h"
#include "coin2/exchange/base/executor/topic_distributor.h"
#include "coin2/exchange/base/feed/arbitration/arbitration_config.h"
#include "coin2/exchange/base/symbology/product.h"


namespace coin2::exchange::base::feed {

using coin2::exchange::base::feed::arbitration::impl::ArbitrationConfigMap;

class TopicRegister {
 public:
  void RegisterLiveShortTopic(
      const MarketExchangeApi& mea,
      executor::TopicRecordSubscriber* subscriber,
      executor::TopicRecordDistributor* dist);

  void RegisterLiveLongTopic(
    const MarketExchangeApi& mea,
    executor::TopicRecordSubscriber* subscriber,
    executor::TopicRecordDistributor* dist);

  void RegisterLiveLongTopicArb(
    const MarketExchangeApi& mea,
    executor::TopicRecordSubscriber* subscriber,
    executor::TopicRecordDistributor* dist,
    const ArbitrationConfigMap& arbitration_config,
    int32_t num_workers);

  std::set<std::string> RegisterFlowTopicsArb(
      const MarketExchangeApi& mea,
      const std::string& workers,
      const std::vector<std::unique_ptr<symbology::IProduct>>& products_,
      executor::TopicRecordSubscriber* subscriber,
      executor::TopicRecordDistributor* dist,
      const ArbitrationConfigMap& arbitration_config);

  std::set<std::string> RegisterFlowTopicsArb(
      const MarketExchangeApi& mea,
      const std::string& workers,
      const std::vector<std::unique_ptr<symbology::IProduct>>& products_,
      executor::TopicRecordSubscriber* subscriber,
      executor::TopicRecordDistributor* dist,
      const ArbitrationConfigMap& arbitration_config,
      const std::string& recipe);

  std::set<std::string> RegisterFlowTopics(
      const MarketExchangeApi& mea,
      const std::string& workers,
      const std::vector<std::unique_ptr<symbology::IProduct>>& products_,
      executor::TopicRecordSubscriber* subscriber,
      executor::TopicRecordDistributor* dist);

  void RegisterTopic(
      const std::string& topic,
      executor::TopicRecordSubscriber* subscriber,
      executor::TopicRecordDistributor* dist);

 private:
  std::unordered_map<char, std::unique_ptr<executor::TopicRecordArbitrator>> arbitrators_;
  std::map<std::pair<char, std::string>, std::unique_ptr<
      executor::TopicRecordArbitrator>> archive_arbitrators_;
};

}  // namespace coin2::exchange::base::feed
